#define _GNU_SOURCE     //在源文件开头定义_GNU_SOURCE宏
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <signal.h>
#include <termios.h>

#define MAXSIZE 150

int uartfd;
int confd;
const char ipAddress[20] = {"192.168.1.102"};
const char ipAddress2[20] = {"172.20.10.8"};
unsigned char read_buf[MAXSIZE];
unsigned char write_buf[MAXSIZE];
int len;

void* pthread_read(void * arg)		//创建线程用以接收数据
{
    while(1)
    {
        int res  = recv(confd, read_buf, sizeof(read_buf), 0);
        write(uartfd, read_buf,res);
        memset(read_buf,0,MAXSIZE);  
    }
}

void* pthread_write(void * arg)		//创建线程用以接收数据
{
    while(1)
    {
        int ret = read(uartfd, write_buf,MAXSIZE);     //一次最多读8个字节数据
        if(ret != 0){
            send(confd,write_buf,MAXSIZE,0);
        }
        memset(write_buf,0,MAXSIZE);
    }
}

int uart_init(int fd){
    struct termios old_cfg;
    if(0>tcgetattr(fd,&old_cfg))
    {
	    return -1;
    }

    struct termios new_cfg;

    memset(&new_cfg,0x0,sizeof(struct termios));

    //配置为原始模式
    cfmakeraw(&new_cfg);

    //使能接收
    new_cfg.c_cflag |= CREAD;

    //设置波特率
    cfsetspeed(&new_cfg,B115200);

    //设置数据位大小
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_cflag |= CS8;//数据位为8位

    //设置奇偶校验


    //奇校验使能
    new_cfg.c_cflag |= (PARODD | PARENB);
    new_cfg.c_iflag |= INPCK;
    //偶校验使能
    new_cfg.c_cflag |= PARENB;
    new_cfg.c_cflag &= ~PARODD; /* 清除 PARODD 标志，配置为偶校验 */
    new_cfg.c_iflag |= INPCK;
    //无校验
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;

    //设置停止位
    // 将停止位设置为一个比特
    new_cfg.c_cflag &= ~CSTOPB;
    // 将停止位设置为 2 个比特
    new_cfg.c_cflag |= CSTOPB;

    //设置MIN和TIME的值
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 0;
    
    //调用tcflush（）清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    //调用tcsetattr()将配置写入设备，使其立即生效
    tcsetattr(fd,TCSANOW,&new_cfg);

}

char *Time()					//获取当前时间
{
	time_t timer;
	struct tm *tblock;
	timer = time(NULL);
	tblock = localtime(&timer);
	return asctime(tblock);
}

void save(char *s)				//储存日志文件
{
    int fd;
    fd = open("journal",O_RDWR|O_APPEND|O_CREAT);

    if(fd < 0)
        perror("open");
    else
    {
        char *buf = Time();
        strcat(buf,s);
                
        write(fd,buf,MAXSIZE);
        lseek(fd,0,SEEK_END);
        
    }
}

int main()
{
    struct termios old_cfg;
    printf("uart init\n");
    
    uartfd = open("/dev/myuart",O_RDWR|O_NOCTTY| O_NDELAY);
    while(0>tcgetattr(uartfd,&old_cfg))
    {
        close(uartfd); 
	    perror("open uart error\n");
	    sleep(5);
        uartfd = open("/dev/myuart",O_RDWR|O_NOCTTY| O_NDELAY);
    }
    uart_init(uartfd);
    printf("set up uart success\n");
    
    printf("socket init\n");
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(7788);
    saddr.sin_addr.s_addr = inet_addr(ipAddress);

    int res = bind(sockfd,(struct sockaddr*)&saddr, sizeof(saddr));
    if(res < 0){
        perror("bind");
     saddr.sin_addr.s_addr = inet_addr(ipAddress2);
     res = bind(sockfd,(struct sockaddr*)&saddr, sizeof(saddr));
     if(res < 0)
        perror("bind");
    }
    listen(sockfd, 5);			//监听端口
    printf("set up socket success\n");

     pthread_t tidR;
        pthread_create(&tidR, NULL, pthread_read, NULL);

        pthread_t tidW;
        pthread_create(&tidW, NULL, pthread_write, NULL);
        
        
     while(1)
    {
        socklen_t len = sizeof(caddr);
         confd = accept(sockfd,(struct sockaddr*)&caddr, &len);
        if(confd < 0)
        {
            perror("accept");
            continue;
        }else
        {
            save(inet_ntoa(caddr.sin_addr));
        }

        printf("Accept confdis:%d, ip=%s\n",confd,inet_ntoa(caddr.sin_addr));

       
        while(0>tcgetattr(uartfd,&old_cfg)){
        printf("open uart failed.\n");  
        close(uartfd);
        uartfd = open("/dev/myuart",O_RDWR|O_NOCTTY| O_NDELAY);
        sleep(5);
       }

    }

}
